﻿using System.Reflection;
using NLite.Internal;

namespace NLite.Reflection
{
    delegate object Func(object target, params object[] arguments);
    delegate void Proc(object target,params object[] arguments);

    /// <summary>
    /// 
    /// </summary>
    public static class FuncExtensions
    {
        /// <summary>
        /// 
        /// </summary>
        /// <param name="method"></param>
        /// <param name="target"></param>
        /// <param name="args"></param>
        /// <returns></returns>
        public static object FastFuncInvoke(this MethodInfo method, object target, params object[] args)
        {
        	if (args == null)
        		args = new object[0];

        	if (target != null && target.GetType().IsValueType)
        		return method.Invoke(target, args);

        	var func = DynamicMethodFactoryProxy.Instance.CreateFuncMethod(method);
        	
        	try
        	{
        		return func(target, args);
        	}
        	catch(TargetInvocationException ex)
        	{
        		throw ex.InnerException;
        	}
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="method"></param>
        /// <param name="target"></param>
        /// <param name="args"></param>
        public static void FastProcInvoke(this MethodInfo method, object target, params object[] args)
        {
        	if (args == null)
        		args = new object[0];

        	if (target != null && target.GetType().IsValueType)
        		method.Invoke(target, args);

        	var func = DynamicMethodFactoryProxy.Instance.CreateProcMethod(method);

        	try
        	{
        		func(target, args);
        	}
        	catch(TargetInvocationException ex)
        	{
        		throw ex.InnerException;
        	}
        }
    }
}
